package com.inspur.edp.bef.bemanager.increment;

import com.inspur.edp.bef.bizentity.GspBusinessEntity;
import com.inspur.edp.bef.bizentity.controlrule.rule.BeControlRule;
import com.inspur.edp.bef.bizentity.controlrule.rule.convert.BeControlRuleConvertor;
import com.inspur.edp.bef.bizentity.controlrule.ruledefinition.entity.BeControlRuleDef;
import com.inspur.edp.bef.bizentity.exceptions.BusinessEntityErrorCodeEnum;
import com.inspur.edp.bef.bizentity.exceptions.BusinessEntityException;
import com.inspur.edp.bef.bizentity.increment.BizEntityIncrement;
import com.inspur.edp.bef.bizentity.increment.extract.BizEntityExtractor;
import com.inspur.edp.bef.bizentity.increment.merger.BizEntityMerger;
import com.inspur.edp.cef.designtime.api.element.increment.GspCommonFieldIncrement;
import com.inspur.edp.cef.designtime.api.element.increment.ModifyFieldIncrement;
import com.inspur.edp.cef.designtime.api.entity.increment.CommonEntityIncrement;
import com.inspur.edp.cef.designtime.api.entity.increment.ModifyEntityIncrement;
import com.inspur.edp.cef.designtime.api.increment.IncrementType;
import com.inspur.edp.cef.designtime.api.increment.property.PropertyIncrement;
import com.inspur.edp.das.commonmodel.entity.increment.CommonModelIncrement;
import com.inspur.edp.lcm.metadata.api.entity.GspMetadata;
import com.inspur.edp.metadata.rtcustomization.api.AbstractCustomizedContent;
import com.inspur.edp.metadata.rtcustomization.spi.CustomizationExtHandler;
import com.inspur.edp.metadata.rtcustomization.spi.args.ChangeMergeArgs;
import com.inspur.edp.metadata.rtcustomization.spi.args.Compare4SameLevelArgs;
import com.inspur.edp.metadata.rtcustomization.spi.args.ExtContentArgs;
import com.inspur.edp.metadata.rtcustomization.spi.args.MetadataMergeArgs;

import java.util.HashMap;
import java.util.Map;

public class BizEntityExtHandler implements CustomizationExtHandler {

    private final static String ContainEnumValues="ContainEnumValues";

    @Override
    public AbstractCustomizedContent getExtContent4SameLevel(Compare4SameLevelArgs args) {
        GspMetadata oldMetadata = args.getOldMetadata();
        GspMetadata newMetadata = args.getMetadata();
        if(oldMetadata == null) {
            throw BusinessEntityException.createException(BusinessEntityErrorCodeEnum.GSP_BEMODEL_BUSINESS_ENTITY_0019);
        }
        if(newMetadata == null) {
            throw BusinessEntityException.createException(BusinessEntityErrorCodeEnum.GSP_BEMODEL_BUSINESS_ENTITY_0020);
        }

        BizEntityExtractor extractor =new BizEntityExtractor(!oldMetadata.isExtended());
        GspBusinessEntity oldBe = (GspBusinessEntity)oldMetadata.getContent();
        GspBusinessEntity newBe = (GspBusinessEntity)newMetadata.getContent();

        BeControlRuleDef def = new BeControlRuleDef();
        BeControlRule rule = new BeControlRule();
        BeControlRuleConvertor.convert2ControlRule(def, rule, oldBe);
        return extractor.extract(oldBe, newBe, rule, def);
    }

    //region changeMerge
    @Override
    public AbstractCustomizedContent changeMerge(ChangeMergeArgs changeMergeArgs) {
        CommonModelIncrement parentChange = (CommonModelIncrement)changeMergeArgs.getParentChage();
        CommonModelIncrement extendChange = (CommonModelIncrement)changeMergeArgs.getChangeToParent();

        if(parentChange==null)
            return null;
        if(extendChange==null)
            return parentChange;
        mergeChangeProperties(parentChange.getChangeProperties(), extendChange.getChangeProperties());

        if(extendChange.getMainEntityIncrement() != null && parentChange.getMainEntityIncrement() != null)
            mergeObjectIncrement(parentChange.getMainEntityIncrement(), extendChange.getMainEntityIncrement());

        return parentChange;
    }


    private void mergeObjectIncrement(ModifyEntityIncrement parentIncrement, ModifyEntityIncrement extendIncrement){

        mergeChangeProperties(parentIncrement.getChangeProperties(), extendIncrement.getChangeProperties());

        for(Map.Entry<String, CommonEntityIncrement> childPair : parentIncrement.getChildEntitis().entrySet()){
            if(childPair.getValue().getIncrementType() != IncrementType.Modify)
                continue;
            if(extendIncrement.getChildEntitis().containsKey(childPair.getKey())) {
                CommonEntityIncrement entityIncrement= extendIncrement.getChildEntitis().get(childPair.getKey());
                if (entityIncrement.getIncrementType()!=IncrementType.Modify)
                    continue;
                mergeObjectIncrement((ModifyEntityIncrement) childPair.getValue(), (ModifyEntityIncrement)entityIncrement);
            }
        }

        for(Map.Entry<String, GspCommonFieldIncrement> elePair : parentIncrement.getFields().entrySet()){
            GspCommonFieldIncrement fieldIncrement = elePair.getValue();
            if(fieldIncrement.getIncrementType() != IncrementType.Modify)
                continue;
            HashMap<String, GspCommonFieldIncrement> extendFields = extendIncrement.getFields();
            if(extendFields.containsKey(elePair.getKey())){
                GspCommonFieldIncrement gspCommonFieldIncrement = extendFields.get(elePair.getKey());
                if (gspCommonFieldIncrement.getIncrementType()!=IncrementType.Modify)
                    continue;
                mergeElementIncrement((ModifyFieldIncrement)fieldIncrement, (ModifyFieldIncrement)gspCommonFieldIncrement);
            }
        }

    }

    private void mergeElementIncrement(ModifyFieldIncrement parentIncrement, ModifyFieldIncrement extendIncrement){
        mergeChangeProperties(parentIncrement.getChangeProperties(), extendIncrement.getChangeProperties());
    }

    private void mergeChangeProperties(HashMap<String, PropertyIncrement> parentChanges, HashMap<String, PropertyIncrement> extendChanges){
        for(Map.Entry<String, PropertyIncrement> changePair : extendChanges.entrySet()){
            if(parentChanges.containsKey(changePair.getKey())){
                // TODO: 2023/8/21 由于枚举之前抽取增量，增量合并时，会将新的增量和已经存在的增量合并，会将新的变更移除，此处暂不处理枚举的增量
                if (ContainEnumValues.equals(changePair.getKey()))
                    continue;
                parentChanges.remove(changePair.getKey());
            }
        }
    }

    //endregion

    @Override
    public AbstractCustomizedContent getExtContent(ExtContentArgs args){//GspMetadata oldMetadata, GspMetadata newMetadata) {
        GspMetadata oldMetadata = args.getBasicMetadata();
        GspMetadata newMetadata = args.getExtMetadata();
        if(oldMetadata == null) {
            throw BusinessEntityException.createException(BusinessEntityErrorCodeEnum.GSP_BEMODEL_BUSINESS_ENTITY_0019);
        }
        if(newMetadata == null) {
            throw BusinessEntityException.createException(BusinessEntityErrorCodeEnum.GSP_BEMODEL_BUSINESS_ENTITY_0020);
        }
        BizEntityExtractor extractor =new BizEntityExtractor();
        GspBusinessEntity oldBe = (GspBusinessEntity)oldMetadata.getContent();
        GspBusinessEntity newBe = (GspBusinessEntity)newMetadata.getContent();

        BeControlRuleDef def = new BeControlRuleDef();
        BeControlRule rule = new BeControlRule();
        BeControlRuleConvertor.convert2ControlRule(def, rule, oldBe);
        return extractor.extract(oldBe, newBe, rule, def);
    }


    @Override
    public GspMetadata merge(MetadataMergeArgs args){//GspMetadata extendMetadata, AbstractCustomizedContent baseIncrement) {

        GspMetadata extendMetadata = args.getExtendMetadata();
        AbstractCustomizedContent baseIncrement = args.getCustomizedContent();
        GspMetadata metadata = (GspMetadata)extendMetadata.clone();
        if(metadata == null) {
            throw BusinessEntityException.createException(BusinessEntityErrorCodeEnum.GSP_BEMODEL_BUSINESS_ENTITY_0021);
        }
        BizEntityMerger merger = new BizEntityMerger(true);
//        GspBusinessEntity extendBe = (GspBusinessEntity)metadata.getContent();
        GspBusinessEntity extendBe = ((GspBusinessEntity)extendMetadata.getContent()).clone();

//        CustomizationService service = SpringBeanUtils.getBean(CustomizationService.class);
//        CommonModelIncrement extendIncrement = (CommonModelIncrement)service.getChangeset(metadata.getHeader().getId() ,null, null);
//        GspBusinessEntity mergedBe = (GspBusinessEntity)merger.merge(extendBe, extendIncrement == null ? new CommonModelIncrement():extendIncrement, (CommonModelIncrement)baseIncrement, new MonkControlRule());
//        metadata.setContent(mergedBe);

        BeControlRuleDef def = new BeControlRuleDef();
        BeControlRule rule = new BeControlRule();
        GspMetadata baseBeMetadata =  args.getRootMetadata();
        BeControlRuleConvertor.convert2ControlRule(def, rule, (GspBusinessEntity)baseBeMetadata.getContent());
        BizEntityIncrement extendIncrement = (BizEntityIncrement)args.getCustomizedContent();
        GspBusinessEntity mergedBe = (GspBusinessEntity)merger.merge(extendBe,(GspBusinessEntity) args.getRootMetadata().getContent(), extendIncrement == null ? new BizEntityIncrement():extendIncrement, (BizEntityIncrement)baseIncrement, rule, def);
        metadata.setContent(mergedBe);

        return metadata;
    }

}
